
#include "pdfParse.h"

static char *logColor = "\033[%dm";

// 解析工具状态
static toolsState_t gToolsState = {0};

/**
 * 调整控制台字色
 */
uint32_t setLogColor(colors_e color)
{
    printf(logColor, color);
    return 0;
}

// 大小端转换函数
uint64_t endianConvert(uint8_t *data, uint32_t datalen)
{
    uint64_t res = 0;
    uint8_t *p = NULL;

    p = (uint8_t *)&res;

    for (int i = 0; i < datalen; i++)
    {
        // printf("%#x ", data[i]);
        // printf("%d  %d\n", i, datalen - i - 1);
        p[i] = data[datalen - i - 1];
    }
    // printf("--> %d \n", res);
    // printf(" \n");
    return res;
}

int8_t pdfHeadParse(uint8_t *data, uint32_t datalen)
{

    if (datalen <= 0)
    {
        return -1;
    }

    pdfheader_t head = {0};

    memcpy(&head, data, sizeof(pdfheader_t));

    printf("flag %c\n", head.flag[0]);
    printf("pdf %c%c%c\n", head.pdf[0], head.pdf[1], head.pdf[2]);
    printf("ver %c%c%c\n", head.ver[0], head.ver[1], head.ver[2]);

    float ver = 0.0;
    sscanf(head.ver, "%f", &ver);

    printf("ver %f\n", ver);

    if (memcmp(head.pdf, "PDF", 3) == 0)
    {
        gToolsState.isPdf = true;
        return 0;
    }
    else
    {
        gToolsState.isPdf = false;
        return -1;
    }
}

/**
 * @brief 检测pdf 支持2 进制,可以不做
 *
 * @param data
 * @param datalen
 * @return int8_t
 */
int8_t pdfCheck(uint8_t *data, uint32_t datalen)
{
    for (uint32_t i = 0; i < datalen; i++)
    {
        printf("%#x ", data[i]);
    }
    printf("\n");

    return 0;
}

/**
 * @brief pdf 字典解析
 *
 * @param data
 * @param datalen
 * @return int8_t
 */
int8_t pdfDictionariesParse(uint8_t *data, uint32_t datalen)
{

    return -1;
}

/**
 * @brief pdf object 解析
 *
 * @param data
 * @param datalen
 * @return int8_t
 */
int8_t pdfObjParse(uint8_t *data, uint32_t datalen)
{
    pdfObj_t *obj = (pdfObj_t *)malloc(sizeof(pdfObj_t));
    if (obj == NULL)
    {
        return -1;
    }
    memset(obj, 0, sizeof(pdfObj_t));

    // 释放资源
    if (obj != NULL)
    {
        free(obj);
        obj = NULL;
    }

    return -1;
}

/**
 * @brief 内容类型检查
 *
 * @param data
 * @param datalen
 * @return int8_t
 */
int8_t contentTypeCheck(uint8_t *data, uint32_t datalen)
{
    if (datalen <= 0)
    {
        return -1;
    }

    // 文件头,可能是pdf文件 可能是新的分段
    if (data[0] == '%')
    {
        if (data[1] == 'P')
        {
            // pdf文件头
            return pdfHeadParse(data, datalen);
        }
        else if (data[1] > 127)
        {
            // 无效段跳过不解析
            return pdfCheck(data, strlen(data));
        }
        else if (data[1] == '%')
        {
            // 文件尾
            printf("pdf file end\n");
            return 0;
        }
    }

    // 字典
    if (data[0] == '<')
    {
        return pdfDictionariesParse(data, datalen);
    }

    // 数据段 obj stream
    if (data[0] > '0' && data[0] < '9')
    {
        // 解析对象并数据重组
        return pdfObjParse(data, datalen);
    }

    return -1;
}

//
int8_t pdfParse(uint8_t *fileAddr)
{
    FILE *file = NULL;
    file = fopen(fileAddr, "rb");
    if (file == NULL)
    {
        printf("MAIN open file fail\n");
        return -1;
    }

    fseek(file, 0, SEEK_SET);

    bool isRun = false;
    do
    {

        uint8_t *pdfbuf = NULL;

        pdfbuf = (uint8_t *)malloc(MAX_READ_SIZE);
        if (pdfbuf == NULL)
        {
            printf("malloc fail\n");
            return -1;
        }

        memset(pdfbuf, 0, MAX_READ_SIZE);

        //
        isRun = true;

        // 读取一行
        fgets((char *)pdfbuf, MAX_READ_SIZE, file);
        printf("read line [%s] read size[%d]\n", pdfbuf, strlen(pdfbuf));

        // 内容分拣
        if (contentTypeCheck(pdfbuf, MAX_READ_SIZE) == -1)
        {
            printf("pdf contentTypeCheck fail\n");

            isRun = false;
        }

        if (pdfbuf != NULL)
        {
            free(pdfbuf);
            pdfbuf = NULL;
        }

    } while (isRun);

    printf("parse ok!\n");
    fclose(file);
    return 0;
}

int main(int argc, char *argv[])
{
    printf("param count %d\n", argc);
    for (int i = 0; i < argc; i++)
    {
        printf("param[%d] %s\n", i, argv[i]);
    }

    if (argc < 2)
    {
        printf("This tool is only used to parse PDF files, and is very basic, for reference only\n");
        printf("Usage is as follows: *.exe *.PDF\n");
        return 0;
    }

    if ((strcmp(argv[1], "help") == 0) || (strcmp(argv[1], "-h") == 0))
    {
        printf("This tool is only used to parse PDF files, and is very basic, for reference only\n");
        printf("Usage is as follows: *.exe *.PDF\n");
        return 0;
    }

    pdfParse(argv[1]);
    return 0;
}
